package com.cskaoyan.javase.oop3._2inner._1member._1basic;

/**
 * 在详细讲解访问特点之前,我们先明确两个重要特点:
 *      1.既然成员内部类和外围类之间是好兄弟,所以它们直接互相访问都不受访问权限限制
 *      2.成员内部类对象依赖于外围类对象而存在.所以:
 *          a.成员内部类的成员方法中,存在几个对象?
 *              有两个
 *              首先成员方法中肯定有this,指向当前对象,就是成员内部类自身对象
 *              然后因为自身对象依赖于外围类对象而存在,所以还存在外围类对象
 *              自身对象用this关键字指向(this是隐含的)
 *              外围类对象用外围类类名.this指向(外围类类名.this也是隐含的)
 *              于是:
 *              在成员内部类的成员方法中,如何访问外围类成员呢?
 *              直接访问,当存在同名情况时:
 *              this访问自身成员,外围类类名.this访问外围类成员
 *
 *          b.外围类的成员方法中,存在几个对象?
 *              成员内部类对象依赖于外围类对象而存在,但是外围类对象不依赖于其他对象
 *              所以这里只存在一个对象,就是外围类自身的对象,用this指向
 *              问:
 *              这时,在外围类的成员方法中,如何访问成员内部类成员呢?
 *              要创建成员内部类对象
 *              如何创建?
 *              直接new创建,因为外围类对象已经存在了
 *              创建对象后,如何访问成员?
 *              用对象名点访问
 *
 *          c.外围类的静态成员方法中,存在几个对象?
 *              静态方法中,没有对象
 *              这时,在外围类的静态成员方法中,如何访问成员内部类成员呢?
 *              先创建外围类对象,再创建成员内部类对象
 *
 *  成员内部类的访问特征
 * 成员内部类的访问特点，主要从以下几个角度研究：
 *      1.成员内部类内部访问外围类
 *          直接访问
 *          如果存在同名成员
 *          this指向自身成员内部类对象
 *          外围类类名.this指向外围类对象
 *      2.外围类访问成员内部类成员
 *          a.成员方法
 *          直接new创建
 *          b.静态方法
 *          先创建外围类对象,再创建成员内部类对象
 *
 *      3.外部类访问成员内部类成员(了解)
 *          思考:
 *          外部类当中,是在成员方法中访问,还是静态方法中访问,有没有区别? 没有区别,因为都没有外围类对象
 *          都需要先创建外围类对象
 *
 *          所以外部类访问成员内部类成员,需要先创建外围类对象,然后在外围类对象的基础上创建成员内部类对象
 *          但是这些过程全部都受访问权限限制
 *
 *      4.成员内部类访问外部类成员(了解)
 *          可以访问,创建外部类对象即可访问
 *          受权限限制
 *
 * @since 10:02
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        /*
            在外部类中创建成员内部类对象
            用引用接收时,需要先告知编译器
                这个成员内部类属于哪个外围类
            语法:
                外围类类名.成员内部类类名 对象名
         */
        EnclosedClazz.InnerClazz ic = ec.new InnerClazz();


        EnclosedClazz.InnerClazz ic3 = ec.new InnerClazz();

        // 以上步骤二合一
        EnclosedClazz.InnerClazz ic2 = new EnclosedClazz().new InnerClazz();

        System.out.println(ic.a);
        // System.out.println(ic.num);
    }
}

class EnclosedClazz {
    int a;
    private int b = 10;
    static int c = 20;
    private static final int D = 10;
    private static final String STRING = "abc";

    // 外围类的成员方法
    public void testMember() {
        // 创建成员内部类对象
        /*
            在外围类对象的基础上创建成员内部类对象
            严格来说应该这么写:
         */
        InnerClazz ic = this.new InnerClazz();
        // 当然this.可以省略,一般可以这么写
        InnerClazz ic2 = new InnerClazz();
        System.out.println(ic.num);
    }

    // 外围类的静态成员方法
    public static void testStatic() {
        /*
            先创建外围类对象
            再在外围类对象的基础上创建成员内部类对象
            可以按照以下写:
         */
        EnclosedClazz ec = new EnclosedClazz();
        InnerClazz ic = ec.new InnerClazz();
        // 以上写法完全可以二合一
        InnerClazz ic2 = new EnclosedClazz().new InnerClazz();
    }

    // 定义成员内部类
    class InnerClazz {
        int a;
        private int num = 10;
        private static final int D = 10;
        static final String STRING = "abc";

        public void test(int a) {
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(EnclosedClazz.this.a);
            System.out.println(b);
            System.out.println(EnclosedClazz.c);
            System.out.println(D);
            System.out.println(EnclosedClazz.D);
        }

    }
}